using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

using System.Security.Cryptography;
using System.Xml.Linq;
using System.IO;
using System.Linq;
using System.Data.OleDb;

namespace SharpPopulatorLib
{

    //public class Old_Generator
    //{

    //    #region Constants

    //    private const String _PasswordCharString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+[]{}\\|;:'\",<.>/?";

    //    #endregion

    //    #region Atributes

    //    private static DateTime _UsingDate;
    //    private static Random _rnd;
    //    private static Char[] _pwdCharArray = _PasswordCharString.ToCharArray();
    //    private static Int16 _PasswordCharacterSize;

    //    #endregion

    //    #region Properties

    //    [Category("Preferences"), Description("To get or set the date to return when i must to generate a Date")]
    //    public static DateTime UsingDate
    //    {
    //        get
    //        {
    //            if (_UsingDate == null)
    //            { return DateTime.Now.Date; }
    //            else
    //            { return _UsingDate; }
    //        }
    //        set
    //        { _UsingDate = value; }
    //    }

    //    [Category("Preferences"), Description("To get or set the number of characters in the password")]
    //    public static Int16 PasswordCharacterSize
    //    {
    //        get { return _PasswordCharacterSize; }
    //        set { _PasswordCharacterSize = value; }
    //    }

    //    #endregion

    //    #region Private Methods

    //    /// <summary>
    //    /// To generate a password with Hash encription.
    //    /// </summary>
    //    /// <returns></returns>
    //    private static String Generate_Hash()
    //    {
    //        //To generate a password with Hash encription.
    //        return Generate_Password().GetHashCode().ToString();
    //    }

    //    /// <summary>
    //    /// To generate a password with MD5 encription
    //    /// </summary>
    //    /// <returns></returns>
    //    private static String Generate_MD5()
    //    {
    //        //To generate a password with MD5 encription
    //        MD5CryptoServiceProvider _md5crypto = new MD5CryptoServiceProvider();
    //        Byte[] _pwdencripted;

    //        _pwdencripted = System.Text.Encoding.ASCII.GetBytes(Generate_Password());
    //        _pwdencripted = _md5crypto.ComputeHash(_pwdencripted);
    //        _md5crypto = null;
    //        return System.Text.Encoding.ASCII.GetString(_pwdencripted);
    //    }

    //    /// <summary>
    //    /// To generate a password with SHA encription.
    //    /// </summary>
    //    /// <returns></returns>
    //    private static String Generate_SHA()
    //    {
    //        // To generate a password with SHA encription.
    //        SHA1CryptoServiceProvider _shacrypto = new SHA1CryptoServiceProvider();
    //        Byte[] _pwdencripted;

    //        _pwdencripted = System.Text.Encoding.ASCII.GetBytes(Generate_Password());
    //        _pwdencripted = _shacrypto.ComputeHash(_pwdencripted);
    //        _shacrypto = null;
    //        return System.Text.Encoding.ASCII.GetString(_pwdencripted);
    //    }

    //    /// <summary>
    //    /// 
    //    /// </summary>
    //    /// <param name="CharacterCount"></param>
    //    /// <returns></returns>
    //    private static String Generate_Password()
    //    {
    //        // To generate a word of caracters, size set in the paramether CharacterCount
    //        String _pwdgenerated = "";

    //        if (_rnd == null)
    //        { _rnd = new Random(); }

    //        for (Int32 _i = 0; _i < _PasswordCharacterSize; _i++)
    //        { _pwdgenerated += _pwdCharArray[_rnd.Next(_pwdCharArray.Length)].ToString(); }
    //        return _pwdgenerated;
    //    }

    //    /// <summary>
    //    /// 
    //    /// </summary>
    //    /// <returns></returns>
    //    private static String GetName()
    //    {
    //        //
    //        List<String> _Names = new List<String>();
    //        XDocument _doc = Utils.XMLDocumentLoader(SourcesType.CatalogSources.ToString());

    //        if (_doc != null)
    //        {
    //            _Names = (from xnode in _doc.Element("Catalogs").Elements("Names")
    //                      select xnode.Element("Name").Value).ToList();
    //        }

    //        _doc = null;
    //        if (_rnd == null)
    //        { _rnd = new Random(); }
    //        return _Names[_rnd.Next(_Names.Count)].Trim();
    //    }

    //    /// <summary>
    //    /// 
    //    /// </summary>
    //    /// <returns></returns>
    //    private static String GetLastName()
    //    {
    //        List<String> _LastNames = new List<String>();
    //        XDocument _doc = Utils.XMLDocumentLoader(SourcesType.CatalogSources.ToString());

    //        if (_doc != null)
    //        {
    //            _LastNames = (from xnode in _doc.Element("Catalogs").Elements("LastNames")
    //                          select xnode.Element("LastName").Value).ToList();
    //        }

    //        _doc = null;
    //        if (_rnd == null)
    //        { _rnd = new Random(); }
    //        return _LastNames[_rnd.Next(_LastNames.Count)].Trim();
    //    }

    //    /// <summary>
    //    /// 
    //    /// </summary>
    //    /// <param name="Name"></param>
    //    /// <param name="LastName"></param>
    //    /// <returns></returns>
    //    private static String GetEMailAddress(String LastName, String Name)
    //    {
    //        //
    //        List<String> _eMail = new List<String>();
    //        XDocument _doc = Utils.XMLDocumentLoader(SourcesType.CatalogSources.ToString());

    //        if (_doc != null)
    //        {
    //            _eMail = (from xnode in _doc.Element("Catalogs").Elements("eMailAddresses")
    //                      select xnode.Element("eMailAddress").Value).ToList();
    //        }

    //        _doc = null;
    //        if (_rnd == null)
    //        { _rnd = new Random(); }
    //        return String.Format("{0}.{1}@{2}", LastName.ToLower(), Name.ToLower(), _eMail[_rnd.Next(_eMail.Count)].Trim());
    //    }

    //    #endregion

    //    #region Public Methods

    //    /// <summary>
    //    /// To generate an integer value less than Maximum value
    //    /// </summary>
    //    /// <param name="Maximum"></param>
    //    /// <returns></returns>
    //    public static Int32 GenerateInteger(Int32 Maximum)
    //    {
    //        // To generate an integer value than Maximum value
    //        if (_rnd == null)
    //        { _rnd = new Random(); }

    //        return _rnd.Next(Maximum);
    //    }

    //    /// <summary>
    //    /// To generate a list of numbers
    //    /// </summary>
    //    /// <returns></returns>
    //    public static List<Int32> GenerateListInt(Int32 Count)
    //    {
    //        //To generate a list of numbers
    //        List<Int32> _List = new List<Int32>();

    //        for (Int32 _i = 0; _i <= Count; _i++)
    //        { _List.Add(_i); }

    //        return _List;
    //    }

    //    /// <summary>
    //    /// To generate a list of numbers
    //    /// </summary>
    //    /// <param name="Start"></param>
    //    /// <param name="Maximum"></param>
    //    /// <returns></returns>
    //    public static List<Int32> GenerateListInt(Int32 Start, Int32 Count)
    //    {
    //        //To generate a list of numbers
    //        List<Int32> _List = new List<Int32>();

    //        for (Int32 _i = Start; _i <= (Start + Count); _i++)
    //        { _List.Add(_i); }

    //        return _List;
    //    }

    //    /// <summary>
    //    /// To generate a String Expressions
    //    /// </summary>
    //    /// <param name="Expression">Expression type</param>
    //    /// <returns>List of Strings</returns>
    //    public static String GenerateString(StringsExpressionsType Expression)
    //    {
    //        // To generate a String Expressions
    //        String _Expression = "";

    //        switch (Expression)
    //        {
    //            case StringsExpressionsType.Address:
    //                { throw new NotImplementedException(); }
    //                break;
    //            case StringsExpressionsType.CompanyName:
    //                { throw new NotImplementedException(); }
    //                break;
    //            case StringsExpressionsType.EMail:
    //                { _Expression = GetEMailAddress(GetName(), GetLastName()); }
    //                break;
    //            case StringsExpressionsType.FullName:
    //                { _Expression = String.Format("{0} {1}", GetName(), GetLastName()); }
    //                break;
    //            case StringsExpressionsType.LastName:
    //                { _Expression = GetLastName(); }
    //                break;
    //            case StringsExpressionsType.Name:
    //                { _Expression = GetName(); }
    //                break;
    //        }
    //        return _Expression;
    //    }

    //    /// <summary>
    //    /// To generate a encripted password
    //    /// </summary>
    //    /// <param name="Encripter"></param>
    //    /// <returns></returns>
    //    public static String GeneratePassword(EncripterType Encripter)
    //    {
    //        //To generate a encripted password
    //        String _pwd = null;

    //        switch (Encripter)
    //        {
    //            case EncripterType.Hash:
    //                { _pwd = Generate_Hash(); }
    //                break;
    //            case EncripterType.MD5:
    //                { _pwd = Generate_MD5(); }
    //                break;
    //            case EncripterType.SHA:
    //                { _pwd = Generate_SHA(); }
    //                break;
    //        }
    //        return _pwd;
    //    }

    //    ///// <summary>
    //    ///// To generate a list of dates
    //    ///// </summary>
    //    ///// <returns></returns>
    //    //public static DateTime GenerateDate()
    //    //{
    //    //    // To generate a dates            
    //    //    return _UsingDate;
    //    //}

    //    #endregion

    //}

    public class Generator : IDisposable
    {

        #region Constants
        
        private const String _PasswordCharString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+[]{}\\|;:'\",<.>/?";
        private const String _ExtendedProperties = "\"text;HDR=Yes;FMT=Delimited\"";

        #endregion

        #region Atributes

        private static Random _rnd;
		private static DateTime _UsingDate;

        private static Dictionary<ResourceType, List<String>> _LoadedResources;


        #endregion

        #region Properties

        [Category("Preferences"), Description("To get or set the date to return when i must to generate a Date")]
        public static DateTime UsingDate
        {
            get
            {
                if (_UsingDate == null)
                { return DateTime.Now.Date; }
                else
                { return _UsingDate; }
            }
            set
            { _UsingDate = value; }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// 
        /// </summary>
        public Generator()
		{
			throw new NotImplementedException();
		}

        #endregion

        #region Private Methods

        /// <summary>
        /// To obtain the data from resources files to generate de random data
        /// </summary>
        /// <param name="Source">Name of the source file</param>
        /// <returns></returns>
        private static List<String> GetResources(ResourceType Resource)
        {
            //To obtain the data from resources files to generate de random data
            List<String> _ResourceList;

            String _ResourcesLocation = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString());
            String _ResourceFile = String.Format("\\Data\\{0}.csv", Resource.ToString());

            String _LocalFullPath = String.Format("{0}{1}", _ResourcesLocation, _ResourceFile);
            String _ParentFullPath = String.Format("{0}{1}", Directory.GetParent(System.IO.Path.GetDirectoryName(_ResourcesLocation)).ToString(), _ResourceFile);

            String _ResouresLocated;

            StreamReader _Resource;

            if (File.Exists(_LocalFullPath))
            { _ResouresLocated = _LocalFullPath; }
            else
            {
                if (File.Exists(_ParentFullPath))
                { _ResouresLocated = _ParentFullPath; }
                else
                { throw new FileNotFoundException("I can't find the resources files."); }
            }

            if (_LoadedResources == null)
            { _LoadedResources = new Dictionary<ResourceType, List<String>>(); }

            if (_LoadedResources.ContainsKey(Resource))
            { return _LoadedResources[Resource]; }
            else
            {
                _Resource = new StreamReader(_ResouresLocated);
                _ResourceList = new List<string>();
                _ResourceList.Clear();
                while (!_Resource.EndOfStream)
                { _ResourceList.Add(_Resource.ReadLine()); }

                _LoadedResources.Add(Resource, _ResourceList);
            }

            return _ResourceList;
        }

        /// <summary>
        /// To generate a String used as Password, using de character set definied in the constant named "_PasswordCharString" 
        /// </summary>
        /// <returns></returns>
        private static String Generate_Password_String(Int32 Size)
        {
            // To generate a word of caracters, size set in the paramether CharacterCount
            String _pwdgenerated = "";

            if (_rnd == null)
            { _rnd = new Random(); }

            for (Int32 _i = 0; _i < Size; _i++)
            { _pwdgenerated += _PasswordCharString[_rnd.Next(_PasswordCharString.Length)].ToString(); }
            return _pwdgenerated;
        }

        /// <summary>
        /// To generate a password with Hash encription.
        /// </summary>
        /// <returns></returns>
        private static String Generate_Hash(String Word)
        {
            //To generate a password with Hash encription.
            return Word.GetHashCode().ToString();
        }

        /// <summary>
        /// To generate a password with MD5 encription
        /// </summary>
        /// <returns></returns>
        private static String Generate_MD5(String Word)
        {
            //To generate a password with MD5 encription
            MD5CryptoServiceProvider _md5crypto = new MD5CryptoServiceProvider();
            Byte[] _pwdencripted;

            _pwdencripted = System.Text.Encoding.ASCII.GetBytes(Word);
            _pwdencripted = _md5crypto.ComputeHash(_pwdencripted);
            _md5crypto = null;
            return System.Text.Encoding.ASCII.GetString(_pwdencripted).ToString();
        }

        /// <summary>
        /// To generate a password with SHA encription.
        /// </summary>
        /// <returns></returns>
        private static String Generate_SHA(String Word)
        {
            // To generate a password with SHA encription.
            SHA1CryptoServiceProvider _shacrypto = new SHA1CryptoServiceProvider();
            Byte[] _pwdencripted;

            _pwdencripted = System.Text.Encoding.ASCII.GetBytes(Word);
            _pwdencripted = _shacrypto.ComputeHash(_pwdencripted);
            _shacrypto = null;
            return System.Text.Encoding.ASCII.GetString(_pwdencripted).ToString();
        }
        
        #endregion

        #region Public Methods

        ///// <summary>
        ///// To generate an integer value less than Maximum value
        ///// </summary>
        ///// <param name="Maximum">Maximum number that can be generated</param>
        ///// <returns></returns>
        //public static Int32 GenerateInteger(Int32 Maximum)
        //{
        //    // To generate an integer value than Maximum value
        //    if (_rnd == null)
        //    { _rnd = new Random(); }

        //    return _rnd.Next(Maximum);
        //}

        /// <summary>
        /// To generate an integer value between Start an End values
        /// </summary>
        /// <param name="Start"></param>
        /// <param name="End"></param>
        /// <returns></returns>
        public static Int32 GenerateInteger(Int32 Start, Int32 End)
        { 
            //
            if (_rnd == null)
            { _rnd = new Random(); }

            return _rnd.Next(Start, End);
        }

        /// <summary>
        /// To generate a list of numbers
        /// </summary>
        /// <param name="Count">Number of integer value to generate</param>
        /// <returns></returns>
        public static List<Int32> GenerateListInt(Int32 Count)
		{
            //To generate a list of numbers
            List<Int32> _List = new List<Int32>();

            for (Int32 _i = 0; _i <= Count; _i++)
            { _List.Add(_i); }

            return _List;
		}

        /// <summary>
        /// To generate a list of numbers
        /// </summary>
        /// <param name="Start">Start number</param>
        /// <param name="Count">Number of integer value to generate</param>
        /// <returns></returns>
        public static List<Int32> GenerateListInt(Int32 Start, Int32 Count)
		{
            //To generate a list of numbers
            List<Int32> _List = new List<Int32>();

            for (Int32 _i = Start; _i <= (Start + Count); _i++)
            { _List.Add(_i); }

            return _List;
		}

        /// <summary>
        /// To generate a random name
        /// </summary>
        /// <returns></returns>
        public static String GenerateName()
		{
            //To generate a random name
            List<String> _Names = new List<String>();

            _Names = GetResources(ResourceType.Name);
            if (_rnd == null)
            { _rnd = new Random(); }
            return _Names[_rnd.Next(_Names.Count)].Trim();
		}

        /// <summary>
        /// To generate a random lastname
        /// </summary>
        /// <returns></returns>
        public static String GenerateLastName()
		{
            //To generate a random lastname
            List<String> _LastNames = new List<String>();

            _LastNames = GetResources(ResourceType.LastName);
            if (_rnd == null)
            { _rnd = new Random(); }
            return _LastNames[_rnd.Next(_LastNames.Count)].Trim();
		}

        /// <summary>
        /// To generate a random full name
        /// </summary>
        /// <returns></returns>
        public static String GenerateFullName()
		{
            //To generate a random full name
            return String.Format("{0} {1}", GenerateName(), GenerateLastName());
		}

        /// <summary>
        /// To generate an random text
        /// </summary>
        /// <returns></returns>
        public static String GenerateText()
		{
			//To generate an random text
            List<String> _Text = new List<String>();

            _Text = GetResources(ResourceType.Description);
            if (_rnd == null)
            { _rnd = new Random(); }
            return _Text[_rnd.Next(_Text.Count)].Trim();
		}

        /// <summary>
        /// To generate a random e-mial address
        /// </summary>
        /// <param name="LastName">Last name used to create the e-mail address</param>
        /// <param name="Name">Name used to create the e-mail address</param>
        /// <param name="Domain">Domain name used to create the e-mail address, EmailDomainType's enumeration value</param>
        /// <param name="CustomDomain">When domain's value is equal to "Other", then this paramether will be used to create de e-mail address, otherwise it's ignored</param>
        /// <returns></returns>
        public static String GenerateEMailAddress(String LastName, String Name, DomainType Domain)
		{
            //To generate a random e-mial address
            List<String> _Domain = new List<String>();

            _Domain = GetResources(ResourceType.Domain);
            if (_rnd == null)
            { _rnd = new Random(); }
            return String.Format("{0}.{1}@{2}", LastName.ToLower(), Name.ToLower(), _Domain[_rnd.Next(_Domain.Count)].Trim());
		}

        /// <summary>
        /// To generate a random e-mial address
        /// </summary>
        /// <param name="LastName">Last name used to create the e-mail address</param>
        /// <param name="Name">Name used to create the e-mail address</param>
        /// <param name="Domain">Domain name used to create the e-mail address, EmailDomainType's enumeration value</param>
        /// <param name="CustomDomain">When domain's value is equal to "Other", then this paramether will be used to create de e-mail address, otherwise it's ignored</param>
        /// <returns></returns>
        public static String GenerateEMailAddress(DomainType Domain, String CustomDomainName)
        {
            //To generate a random e-mial address
            List<String> _Domain = new List<String>();

            if (Domain == DomainType.Unique)
            { return String.Format("{0}.{1}@{2}", Generator.GenerateLastName().ToLower(), Generator.GenerateName().ToLower(), _Domain[_rnd.Next(_Domain.Count)].Trim()); }
            else
            { 
                _Domain = GetResources(ResourceType.Domain);
                if (_rnd == null)
                { _rnd = new Random(); }
                return String.Format("{0}.{1}@{2}", Generator.GenerateLastName().ToLower(), Generator.GenerateName().ToLower(), _Domain[_rnd.Next(_Domain.Count)].Trim());
            }            
        }

        /// <summary>
        /// To generate a password string
        /// </summary>
        /// <param name="Encripter">Encripter tipe, EncripterType's enumeration value</param>
        /// <param name="Size">Number of the password before the encriptation</param>
        /// <returns></returns>
		public static String GeneratePassword(EncripterType Encripter, Int32 Size)
		{
			//To generate a password string
            String _GeneratedPassword = Generate_Password_String(Size);

            switch (Encripter)
            { 
                case EncripterType.Hash:
                { _GeneratedPassword = Generate_SHA(_GeneratedPassword); }
                break;
                case EncripterType.MD5:
                { _GeneratedPassword = Generate_MD5(_GeneratedPassword); }
                break;
                case EncripterType.SHA:
                { _GeneratedPassword = Generate_SHA(_GeneratedPassword); }
                break;
            }

            return _GeneratedPassword;

		}

        ///// <summary>
        ///// 
        ///// </summary>
        //public static void TestGetResourcesMethod()
        //{
        //    GetResources(ResourceType.Name);
        //}

        #endregion

        #region IDisposable Members

        void IDisposable.Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    
    }

}